package com.actionsoft;

import com.actionsoft.Plugin.Orgoption;
import com.actionsoft.bpms.bo.engine.BO;
import com.actionsoft.bpms.bpmn.engine.model.run.delegate.ProcessInstance;
import com.actionsoft.bpms.commons.database.RowMapper;
import com.actionsoft.bpms.commons.formfile.model.FormFileModel;
import com.actionsoft.bpms.commons.formfile.model.delegate.FormFile;
import com.actionsoft.bpms.org.model.UserModel;
import com.actionsoft.bpms.server.bind.annotation.Controller;
import com.actionsoft.bpms.server.bind.annotation.HandlerType;
import com.actionsoft.bpms.server.fs.DCContext;
import com.actionsoft.bpms.util.DBSql;
import com.actionsoft.exception.AWSDataAccessException;
import com.actionsoft.sdk.local.SDK;
import com.actionsoft.sdk.local.api.BOAPI;
import com.actionsoft.sdk.local.api.BOQueryAPI;
import com.alibaba.nacos.common.http.param.MediaType;
import com.alibaba.nacos.common.http.param.Query;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.etcd.jetcd.shaded.io.grpc.Context;
import org.apache.cxf.jaxrs.ext.multipart.Attachment;
import org.apache.cxf.jaxrs.ext.multipart.Multipart;
import org.apache.poi.ss.formula.functions.T;
import org.apache.xmlbeans.impl.xb.xsdschema.Public;

import javax.ws.rs.*;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Controller(type = HandlerType.RESTFUL, apiName = "com.awspass.user.apps.appfruit", desc = "校友会接口")
public class InfoController {

    // 微信小程序配置
    private static final String APP_ID = "wx8c6a587df8a16008";
    private static final String APP_SECRET = "9239382505ef10058f1e2b8d02f9733d";

    //                         @QueryParam("uid") String uid,
    //                         @QueryParam("pwd") String pwd,
    @GET
    @Path("/api/getinfo")
    public String getinfo(@QueryParam("boName") String boName,
                          @QueryParam("fields") String fieldsCsv,
                          @QueryParam("sort") String sortField,
                          @QueryParam("limit") Integer limit,
                          @QueryParam("page") Integer page) throws IOException {


        List<Map<String, Object>> result = new ArrayList<>();
        // 1. 参数校验
        if (boName == null || boName.trim().isEmpty()) {
            throw new WebApplicationException("boName 不能为空", 400);
        }
        List<BO> bo = SDK.getBOAPI().query(boName).list();
        if (sortField != null && !sortField.trim().isEmpty()) {
            bo = SDK.getBOAPI().query(boName).orderBy(sortField).desc().list();
        }

        if (limit != null) {
            int pageSize = limit;
            int firstRow = (page - 1) * pageSize;  // 来自 @QueryParam("page")
            bo = SDK.getBOAPI().query(boName).listPage(firstRow, pageSize);
        }

        for (BO record : bo) {
            Map<String, Object> map = new LinkedHashMap<>();
            String boid = record.getId();
            if (fieldsCsv == null || fieldsCsv.trim().isEmpty()) {
                // 直接放整条记录
                map = record.asMap();
                // 2. 针对所有可能存文件的字段统一处理
                Set<String> fileFields = record.asMap().keySet();
                for (String field : fileFields) {
                    List<String> urls = getFieldFileUrls(boid, field);
                    if (!urls.isEmpty()) {
                        map.put(field, urls);
                    }
                }
            } else {
                //获取图片功能
                List<String> fields = Arrays.asList(fieldsCsv.split(","));
                for (String field : fields) {
                    List<String> urls = getFieldFileUrls(boid, field);
                    if (!urls.isEmpty()) {
                        map.put(field, urls);
                    } else {
                        map.put(field, record.get(field));
                    }
                }
            }
            result.add(map);
        }

        return new ObjectMapper().writerWithDefaultPrettyPrinter()
                .writeValueAsString(result);
    }

    @GET
    @Path("/api/getinfo/by")
    public String getinfoby(
            @QueryParam("boName") String boName,
            @QueryParam("sqlWhere") String sqlWhere,     // 例如:  STATUS=:STATUS OR AGE>:AGE
            @QueryParam("params") String paramsKV,      // 例如:  STATUS,Active;AGE,18
            @QueryParam("fieldsCsv") String fieldsCsv,
            @QueryParam("sort")     String sortField,
            @QueryParam("limit")    Integer limit,
            @QueryParam("page")     Integer page)throws IOException {

        // 1. 基本校验
        if (boName == null || boName.trim().isEmpty()) {
            throw new WebApplicationException("boName 不能为空", 400);
        }

        // 2. 把 "key,val;key2,val2" 解析成 Map
        Map<String, Object> params = new HashMap<>();
        if (paramsKV != null && !paramsKV.trim().isEmpty()) {
            for (String pair : paramsKV.split(";")) {
                String[] kv = pair.split(",", 2);
                if (kv.length == 2) {
                    params.put(kv[0].trim(), kv[1].trim());
                }
            }
        }

        // 2. 构造查询
        BOQueryAPI query;
        if (sqlWhere == null || sqlWhere.trim().isEmpty()) {
            query = SDK.getBOAPI().query(boName);
        }else{
            query = SDK.getBOAPI().query(boName).addQuerySqlWhere(sqlWhere, params);
        }
        //排序（可选）
        if (sortField != null && !sortField.trim().isEmpty()) {
            query = query.orderBy(sortField).desc();
        }
        List<BO> boList;
        // 4. 分页（可选）
        if (limit != null && limit > 0) {
            int pageSize = limit;
            int firstRow = (page == null || page < 1 ? 1 : page) - 1;
            firstRow *= pageSize;
            boList = query.listPage(firstRow, pageSize);
        } else {
            boList = query.list();
        }

        // 4. 组装结果
        List<Map<String, Object>> result = new ArrayList<>();
        for (BO record : boList) {
            Map<String, Object> map = new LinkedHashMap<>();
            String boid = record.getId();

            if (fieldsCsv == null || fieldsCsv.trim().isEmpty()) {
                map = record.asMap();
                Set<String> fileFields = record.asMap().keySet();
                for (String field : fileFields) {
                    List<String> urls = getFieldFileUrls(boid, field);
                    if (!urls.isEmpty()) {
                        map.put(field, urls);
                    }
                }
            } else {
                for (String field : fieldsCsv.split(",")) {
                    List<String> urls = getFieldFileUrls(boid, field);
                    if (!urls.isEmpty()) {
                        map.put(field, urls);
                    } else {
                        map.put(field, record.get(field));
                    }
                }
            }
            result.add(map);
        }

        return new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(result);
    }

    /*********************   6  ***************************/
    //6.1
    @GET
    @Path("/api/getcardinfo")
    public String getcardinfo(@QueryParam("ALUMNI_ID") String ALUMNI_ID) throws IOException {
        List<BO> bo = SDK.getBOAPI().query("BO_EU_XIAOYOUXINXI").addQuery("ALUMNI_ID =", ALUMNI_ID).list();
        String boid = bo.get(0).getId();
        String[] keepFields = {"ALUMNI_ID","ALUMNI_NAME","CONTACT_PHONE","COLLEGE_EXPERIENCE",
                "COLLEGE_IN","COLLEGE_OUT","COLLEGE_NAME","MAJOR"};

        List<String> urls = new ArrayList<>();
        urls.add(buildFileUrl(boid, "ALUMNI_COVER"));
        // 2. 把每条 BO 只保留指定字段
        List<Map<String, Object>> slim = bo.stream()
                .map(b -> {
                    Map<String, Object> m = new LinkedHashMap<>();
                    for (String f : keepFields) {
                        m.put(f, b.get(f));
                    }
                    m.put("ALUMNI_COVER", urls);
                    m.put("WORK_COMPANY", SDK.getBOAPI().query("BO_EU_XIAOYOUTUOZHANXINXI").addQuery("ALUMNI_ID =", b.get("ALUMNI_ID")).detail().get("WORK_COMPANY"));
                    return m;
                })
                .collect(Collectors.toList());

        return new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(slim);
    }
    /*********************   6  ***************************/

    @GET
    @Path("/api/getextendinfo")
    public String getextendinfo(@QueryParam("ALUMNI_ID") String ALUMNI_ID) throws IOException {
        List<BO> bo = SDK.getBOAPI().query("BO_EU_XIAOYOUTUOZHANXINXI").addQuery("ALUMNI_ID =", ALUMNI_ID).list();
        String boid = bo.get(0).getId();

        List<String> urls = new ArrayList<>();
        // 4. 组装结果（保持与原逻辑一致）
        List<Map<String, Object>> result = new ArrayList<>();
        for (BO record : bo) {
            Map<String, Object> map = record.asMap();
            urls.add(buildFileUrl(boid, "ALUMNI_COVER"));
            map.put("ALUMNI_COVER", urls);
            result.add(map);
        }
        return new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(result);
    }
/*******************               2                *******************/
    @GET
    @Path("/api/firstpage")
    public String getfirstpage() throws IOException {
        // 1. 查母校新闻
        List<BO> newsList = SDK.getBOAPI().query("BO_EU_1752893525435")
                .orderBy("NEW_TIME").desc()
                .list().stream().limit(10).collect(Collectors.toList());

        // 2. 查校友活动
        List<BO> activityList = SDK.getBOAPI().query("BO_EU_1752895052880")
                .orderBy("START_TIME").desc()
                .list().stream().limit(10).collect(Collectors.toList());

        // 3. 查校友动态
        List<BO> alumninewsList = SDK.getBOAPI().query("BO_EU_1752894680960")
                .addQuery("STATUS =","已通过")
                .orderBy("ALUMNINEWS_TIME").desc()
                .list().stream().limit(10).collect(Collectors.toList());

        // 4. 合并三个列表
        List<Map<String, Object>> mergedList = new ArrayList<>();

        for (BO bo : newsList) {
            Map<String, Object> map = bo.asMap();
            String url = buildFileUrl(bo.getId(),"NEW_COVER");
            map.put("NEW_COVER", url);
            map.put("publishTime", bo.get("NEW_TIME"));
            mergedList.add(map);
        }

        for (BO bo : activityList) {
            Map<String, Object> map = bo.asMap();
            String url = buildFileUrl(bo.getId(),"ACTIVITY_COVER");
            map.put("ACTIVITY_COVER", url);
            map.put("publishTime", bo.get("START_TIME"));
            mergedList.add(map);
        }

        for (BO bo : alumninewsList) {
            Map<String, Object> map = bo.asMap();
            String url = buildFileUrl(bo.getId(),"ALUMNINEWS_COVER");
            map.put("ALUMNINEWS_COVER", url);
            map.put("publishTime", bo.get("ALUMNINEWS_TIME"));
            mergedList.add(map);
        }

        // 5. 按时间排序并取前10条
        //转换格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        List<Map<String, Object>> sortedList = mergedList.stream()
                .filter(m -> m.get("publishTime") != null)
                .sorted((m1, m2) -> {
                    try {
                        Date t1 = sdf.parse((String)m1.get("publishTime"));
                        Date t2 = sdf.parse((String)m2.get("publishTime"));
                        return t2.compareTo(t1);// 降序
                    } catch (ParseException e) {
                        throw new RuntimeException(e);
                    }
                })
                .limit(10)
                .collect(Collectors.toList());


        return new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(sortedList);
    }
    /*******************               2                *******************/
/**********           3              ***********/
    //3.2
    @GET
    @Path("/api/getpersonal")
    public String getpersonal(@QueryParam("ALUMNI_ID") String ALUMNI_ID) throws IOException {
        System.out.println("ALUMNI_ID=" + ALUMNI_ID);
        List<BO> bo = SDK.getBOAPI().query("BO_EU_XIAOYOUXINXI").addQuery("ALUMNI_ID =", ALUMNI_ID).list();
        String boid = bo.get(0).getId();
        Object hide = bo.get(0).get("HIDE");
        String[] keepFields;
        //Map<String, Object> workInfo = new LinkedHashMap<>();
        if (hide.equals("非隐藏")) {
            keepFields = new String[]{"ALUMNI_ID", "ALUMNI_NAME", "COLLEGE_IN", "COLLEGE_NAME","MAJOR",
                    "PHONE","CONTACT_PHONE","COLLEGE_EXPERIENCE"};
        }else{
            keepFields = new String[]{"ALUMNI_ID", "ALUMNI_NAME", "COLLEGE_IN", "COLLEGE_NAME","MAJOR"};
        }
        String  urls = buildFileUrl(boid, "ALUMNI_COVER");
        Map<String, Object> result = new LinkedHashMap<>();
        for (String f : keepFields) {
            result.put(f, bo.get(0).get(f));
        }
        result.put("ALUMNI_COVER", urls);

        // 非隐藏时再追加 WORK_COMPANY、WORK_EXPERIENCE
        if ("非隐藏".equals(hide)) {
            // 从拓展信息表查
            List<BO> extendList = SDK.getBOAPI().query("BO_EU_XIAOYOUTUOZHANXINXI").addQuery("ALUMNI_ID =", ALUMNI_ID).list();
            if (!extendList.isEmpty()) {
                BO ext = extendList.get(0);
                result.put("WORK_COMPANY",    ext.get("WORK_COMPANY"));
                result.put("WORK_EXPERIENCE", ext.get("WORK_EXPERIENCE"));
            }
        }
        return new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(result);
    }
    //3.3
    @GET
    @Path("/api/getorg")
    public String getorg(@QueryParam("ALUMNI_ID") String ALUMNI_ID,
                         @QueryParam("Is") String is) throws IOException {

        List<BO> bo = SDK.getBOAPI().query("BO_EU_XIAOYOUXINXI").addQuery("ALUMNI_ID =", ALUMNI_ID).list();
        Object hide = "";
        if(is.equals("me")){
            hide = "非隐藏";
        }
        else{
            hide = bo.get(0).get("HIDE");
        }
        List<Map<String, Object>> result = new ArrayList<>();
        try {
            if (hide.equals("非隐藏")) {
                List<BO> orgids = SDK.getBOAPI().query("BO_EU_XIAOYOUHUIZUZHICHENGYUAN")
                        .addQuery("ALUMNI_ID =", ALUMNI_ID).list();
                for (BO boorg : orgids) {
                    Map<String, Object> map = new LinkedHashMap<>();
                    Object org_id = boorg.get("ORG_ID");
                    Object name = SDK.getBOAPI().query("BO_EU_XIAOYOUHUIZUZHIXINXI").addQuery("ORG_ID =", org_id).detail().get("ORG_NAME");
                    String boid = SDK.getBOAPI().query("BO_EU_XIAOYOUHUIZUZHIXINXI").detail().getId();
                    Object status = SDK.getBOAPI().query("BO_EU_XIAOYOUHUIZUZHICHENGYUAN").addQuery("ORG_ID =",org_id).addQuery("ALUMNI_ID =",ALUMNI_ID).detail().get("AUDIT_STATUS");
                    Long activitycount = SDK.getBOAPI().query("BO_EU_1752895052880").addQuery("ORG_ID =", org_id).count();
                    Long orgmenber = SDK.getBOAPI().query("BO_EU_XIAOYOUHUIZUZHICHENGYUAN").addQuery("ORG_ID =", org_id).addQuery("AUDIT_STATUS !=", "待审核").count();
                    map.put("ORG_NAME", name);
                    map.put("ORG_ID", org_id);
                    map.put("AUDIT_STATUS", status);
                    map.put("ORG_PICTURE", buildFileUrl(boid, "ORG_PICTURE"));
                    map.put("ActivityCount", activitycount);
                    map.put("ORG_menber_count", orgmenber);
                    result.add(map);
                }
            } else {
                return "已隐藏信息";
            }
        }catch (Exception e){
                return new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString("尚未加入组织");

        }
        return new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(result);
    }
    /**********           3              ***********/

    @GET
    @Path("/api/addressbook/exchange")
    public String getaddressbook(@QueryParam("ALUMNI_ID") String ALUMNI_ID,
                                 @QueryParam("MODEL")   String model) throws IOException {

        if (ALUMNI_ID == null || ALUMNI_ID.trim().isEmpty()) {
            return new ObjectMapper().writeValueAsString(Collections.emptyList());
        }

        List<BO> extendinfo = new ArrayList<>();

        /* 1. 按模块分别查询交换记录 */
        switch (model) {
            case "通讯录":
                extendinfo = SDK.getBOAPI()
                        .query("BO_EU_XIAOYOUJIAOHUAN")
                        .sql("SELECT * FROM BO_EU_XIAOYOUJIAOHUAN " +
                                "WHERE (EXCHANGE_ALUMNI_ID = " + ALUMNI_ID +
                                "        OR BEEXCHANGE_ALUMNI_ID = " + ALUMNI_ID + ") " +
                                "  AND EXCHANGE_STATUS = '已交换' " +
                                "ORDER BY CREATEDATE DESC")
                        .list();
                break;

            case "给我的":
                extendinfo = SDK.getBOAPI().query("BO_EU_XIAOYOUJIAOHUAN")
                        .sql("SELECT * FROM BO_EU_XIAOYOUJIAOHUAN " +
                                "WHERE (BEEXCHANGE_ALUMNI_ID = " + ALUMNI_ID + ") " +
                                " AND EXCHANGE_STATUS != '已交换' " +
                                "ORDER BY CREATEDATE DESC")
                        .list();
                break;

            case "我发的":
                extendinfo = SDK.getBOAPI()
                        .query("BO_EU_XIAOYOUJIAOHUAN")
                        .sql("SELECT * FROM BO_EU_XIAOYOUJIAOHUAN " +
                                "WHERE (EXCHANGE_ALUMNI_ID = " + ALUMNI_ID + ") " +
                                " AND EXCHANGE_STATUS != '已交换' " +
                                "ORDER BY CREATEDATE DESC")
                        .list();
                break;

            default:
                return new ObjectMapper().writeValueAsString(Collections.emptyList());
        }

        /* 2. 各模块独立组装结果 */
        List<Map<String, Object>> result = new ArrayList<>();
        for (BO record : extendinfo) {
            String peerId;
            switch (model) {
                case "通讯录":
                    peerId = ALUMNI_ID.equals(record.getString("EXCHANGE_ALUMNI_ID"))
                            ? record.getString("BEEXCHANGE_ALUMNI_ID")
                            : record.getString("EXCHANGE_ALUMNI_ID");
                    break;
                case "给我的":
                    peerId = record.getString("EXCHANGE_ALUMNI_ID");
                    break;
                case "我发的":
                default:
                    peerId = record.getString("BEEXCHANGE_ALUMNI_ID");
                    break;
            }

            List<BO> alumniInfos = SDK.getBOAPI()
                    .query("BO_EU_XIAOYOUXINXI")
                    .addQuery("ALUMNI_ID =", peerId)
                    .list();

            for (BO info : alumniInfos) {
                Map<String, Object> map = new LinkedHashMap<>();
                map.put("ALUMNI_NAME",    info.get("ALUMNI_NAME"));
                map.put("ALUMNI_COVER",   buildFileUrl(info.getId(), "ALUMNI_COVER"));
                map.put("ALUMNI_ID",      info.get("ALUMNI_ID"));
                map.put("EXCHANGE_STATUS",record.get("EXCHANGE_STATUS"));
                map.put("UPDATEDATE",   info.get("UPDATEDATE"));
                result.add(map);
            }
        }

        /* 3. 返回对应模块的 JSON */
        return new ObjectMapper().writerWithDefaultPrettyPrinter()
                .writeValueAsString(result);
    }

    @GET
    @Path("/api/orgcount")
    public String getorgcount(@QueryParam("ALUMNI_ID") String ALUMNI_ID) throws IOException {
        Long orgcount = SDK.getBOAPI().query("BO_EU_XIAOYOUHUIZUZHICHENGYUAN")
                .addQuery("ALUMNI_ID =", ALUMNI_ID).addQuery("AUDIT_STATUS !=","待审核").count();

        return new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(orgcount);
    }

    //7.6我的活动
    @GET
    @Path("/api/getmyactivity")
    public String getmyactivity(@QueryParam("ALUMNI_ID") String ALUMNI_ID) throws IOException {
        List<BO> boList= SDK.getBOAPI().query("BO_EU_REGISTRATION_INFORMATION")
                .addQuery("ALUMNI_ID =",ALUMNI_ID).list();
        List<Map<String, Object>> result = new ArrayList<>();
        for (BO record : boList) {
            List<BO> activity = SDK.getBOAPI()
                    .query("BO_EU_1752895052880")
                    .addQuery("ACTIVITY_ID =",record.get("ACTIVITY_ID")).list();

            if (activity.isEmpty()){
                return "暂未参加活动！！！";
            }
            Map<String, Object> map = new LinkedHashMap<>();
            String boid = activity.get(0).getId();
            String url = buildFileUrl(boid, "ACTIVITY_COVER");
            map.put("ACTIVITY_ID",   activity.get(0).get("ACTIVITY_ID"));
            map.put("ACTIVITY_NAME", activity.get(0).get("ACTIVITY_NAME"));
            map.put("ACTIVITY_COVER", url);
            map.put("START_TIME",    activity.get(0).get("START_TIME"));
            map.put("LOCATION",      activity.get(0).get("LOCATION"));
            map.put("STATUS",     activity.get(0).get("STATUS"));
            map.put("ACTIVITY_TYPE", activity.get(0).get("ACTIVITY_TYPE"));
            map.put("ONLINE",   activity.get(0).get("ONLINE"));
            map.put("TOP",     activity.get(0).get("TOP"));
            result.add(map);
        }
        return new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(result);
    }

    @POST
    @Path("/api/addfeedback")
    public String addfeedback(@QueryParam("ALUMNI_ID") String ALUMNI_ID,
                              @QueryParam("ALUMNI_NAME") String ALUMNI_NAME,
                              @QueryParam("FEEDBACK_CONTEXT") String FEEDBACK_CONTEXT) throws IOException {
        //创建流程id，启动流程获取流程id
        ProcessInstance process = SDK.getProcessAPI().createProcessInstance
                ("obj_933cfb29a3364fdaae35ca4d43890c50",ALUMNI_ID,"添加反馈流程");
        /*ProcessExecuteQuery start =*/
        SDK.getProcessAPI().start(process);
        String bindid=process.getId();
        //创建新BO，保存信息
        BO bo = new BO();
        bo.set("ALUMNI_ID",ALUMNI_ID);
        bo.set("ALUMNI_NAME",ALUMNI_NAME);
        bo.set("FEEDBACK_CONTEXT",FEEDBACK_CONTEXT);
        bo.set("BINDID",bindid);
        int count = SDK.getBOAPI().create("BO_EU_FEEDBACK",bo,bindid,ALUMNI_ID);//写死账户需修改

        if (count == 0) {
            return "报名失败，出现异常";
        }

        String issuccess = autocompleteTask(process.getStartTaskInstId(),ALUMNI_ID);

        //返回成功 JSON
        Map<String, Object> result = new HashMap<>();
        result.put("count", count);
        result.put("msg", issuccess);

        return new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(result);
    }

    @POST
    @Path("/api/addregistration")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public String addregistration(Map<String, Object> maps) throws IOException {

        /* 2. 创建业务对象并自动写入所有字段 */
        BO bo = new BO();
        for (Map.Entry<String, Object> e : maps.entrySet()) {
            bo.set(e.getKey(), e.getValue());
        }
        String ALUMNI_ID = (String) bo.get("ALUMNI_ID");
        /* 1. 启动流程 */
        ProcessInstance process = SDK.getProcessAPI().createProcessInstance(
                        "obj_861bd1b055aa45b78edcd394d56b505a", ALUMNI_ID, "报名流程");
        SDK.getProcessAPI().start(process);
        String bindid = process.getId();

        bo.set("BINDID", bindid); // 流程主键

        int count = SDK.getBOAPI().create("BO_EU_REGISTRATION_INFORMATION",bo,bindid,ALUMNI_ID);

        /* 3. 返回成功 JSON */
        if (count == 0) {
            return "报名失败，出现异常";
        }
        String issuccess = autocompleteTask(process.getStartTaskInstId(),ALUMNI_ID);
        Map<String, Object> result = new HashMap<>();
        result.put("count", count);
        result.put("msg", issuccess);
        return new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(result);

    }

    /**************        7      ***************/

    //上传图片功能
    @POST
    @Path("/api/upcover")
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    @Produces(MediaType.APPLICATION_JSON)
    public Response uploadSingleFile(
            @Multipart("ALUMNI_ID") String ALUMNI_ID,
            @Multipart(value = "file") Attachment attachment) {

        // 1. 业务对象、字段、记录主键
        final String boName   = "BO_EU_XIAOYOUXINXI";        // 业务对象
        final String fieldKey = "ALUMNI_COVER";             // 要写入的字段

        BO bo = SDK.getBOAPI().query(boName).addQuery("ALUMNI_ID = ",ALUMNI_ID).detail();
        String boid = bo.getId();//获取数据记录id

        System.out.println("开始获取附件:");
        List<FormFile> oldFiles = SDK.getBOAPI().getFiles(boid, fieldKey);
        if (oldFiles != null && !oldFiles.isEmpty()) {
            System.out.println("存在原有附件,先删除");
            String modleid = oldFiles.get(0).getId();//获取附件记录id
            System.out.println("附件id："+modleid);
            //1.先删除原来的图片
            SDK.getBOAPI().removeFile(modleid);
        }
        //2.新增图片到字段中
        InputStream in = attachment.getObject(InputStream.class);
        try {
            FormFileModel formFile = new FormFileModel();
            formFile.setRemark("头像上传");
            formFile.setBoName(boName);         // 业务对象
            formFile.setBoItemName(fieldKey);     // 字段名
            formFile.setCreateUser("admin");
            formFile.setBoId(boid);
            /* 文件自身信息 */
            formFile.setFileName(
                    "THFile-" + new SimpleDateFormat("yyyyMMddHHmm").format(new Date()) + ".docx"
            );
            formFile.setAppId("com.awspaas.user.apps.xiaoyouhui");
            System.out.println(formFile.getFileName());
            SDK.getBOAPI().upFile(formFile,in);

            /* 3. 返回结果 */
            System.out.println("返回结果");
            Map<String, Object> result = new HashMap<>();
            result.put("success", true);
            result.put("校友名:", bo.get("ALUMNI_ID"));
            result.put("附件id:",SDK.getBOAPI().getFiles(boid, "ALUMNI_COVER").get(0).getId());
            return Response.ok(result).build();

        } catch (Exception e) {
            Map<String, Object> error = new HashMap<>();
            error.put("error", e.getMessage());
            return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
                    .entity(error)
                    .build();
        }
    }


    @GET
    @Path("/api/getUserInfo")
    public String getUserInfo(@QueryParam("ALUMNI_ID") String ALUMNI_ID) throws IOException {
        Map<String, Object> bo1 = SDK.getBOAPI().query("BO_EU_XIAOYOUXINXI")
                .addQuery("ALUMNI_ID =",ALUMNI_ID)
                .addQuery("AUTH_STATUS =","已注册").detail().asMap();
        bo1.remove("PHONE");
        bo1.remove("ID_CARD");
        bo1.remove("ID");
        Map<String,Object> bo2 = SDK.getBOAPI().query("BO_EU_XIAOYOUTUOZHANXINXI")
                .addQuery("ALUMNI_ID =",ALUMNI_ID).detail().asMap();
        Map<String,Object> merged = new HashMap<>(bo1);
        bo2.remove("ALUMNI_ID");
        merged.putAll(bo2);
        return new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(merged);
    }

    @PUT
    @Path("/api/modify/extendinfo")
    @Consumes(MediaType.APPLICATION_JSON)          // 必须声明
    @Produces(MediaType.APPLICATION_JSON)
    public String modifyextendinfo(Map<String, Object> updates) throws IOException {

        /* 1. 从 JSON 里拿到 ALUMNI_ID */
        Object idObj = updates.remove("ALUMNI_ID");   // 取出同时把它从更新字段里删掉
        if (idObj == null) {
            throw new WebApplicationException("ALUMNI_ID 不能为空", 400);
        }
        String ALUMNI_ID = idObj.toString().trim();
        if (ALUMNI_ID.isEmpty()) {
            throw new WebApplicationException("ALUMNI_ID 不能为空", 400);
        }

        /* 2. 查询记录 */
        BO alumni = SDK.getBOAPI()
                .query("BO_EU_XIAOYOUTUOZHANXINXI")
                .addQuery("ALUMNI_ID = ", ALUMNI_ID)
                .detail();
        if (alumni == null) {
            throw new WebApplicationException("未找到校友记录", 404);
        }

        /* 3. 动态更新剩余字段 */
        for (Map.Entry<String, Object> entry : updates.entrySet()) {
            alumni.set(entry.getKey(), entry.getValue());
        }

        /* 4. 保存并返回最新数据 */
        SDK.getBOAPI().update("BO_EU_XIAOYOUTUOZHANXINXI", alumni);
        Map<String, Object> maptuo = SDK.getBOAPI()
                .query("BO_EU_XIAOYOUTUOZHANXINXI")
                .addQuery("ALUMNI_ID = ", ALUMNI_ID)
                .detail()
                .asMap();
        Map<String,Object> map = SDK.getBOAPI()
                .query("BO_EU_XIAOYOUXINXI")
                .addQuery("ALUMNI_ID = ", ALUMNI_ID)
                .detail()
                .asMap();
        map.remove("ID_CARD");
        map.remove("ID");
        map.remove("BINDID");
        maptuo.remove("ID");
        maptuo.remove("BINDID");
        maptuo.remove("ALUMNI_ID");
        map.putAll(maptuo);
        return new ObjectMapper().writerWithDefaultPrettyPrinter()
                .writeValueAsString(map);
    }

    /**************        7      ***************/

    @PUT
    @Path("/api/modify/exchangestate")
    public String modifyexchangestate(@QueryParam("EXCHANGE_ALUMNI_ID") String EXALUMNI_ID,
                                      @QueryParam("BEEXCHANGE_ALUMNI_ID") String BEEXALUMNI_ID,
                                      @QueryParam("STATUS") String status) throws IOException {

        if (EXALUMNI_ID == null || EXALUMNI_ID.trim().isEmpty()) {
            throw new WebApplicationException("EXALUMNI_ID 不能为空", 400);
        }
        if (BEEXALUMNI_ID == null || BEEXALUMNI_ID.trim().isEmpty()) {
            throw new WebApplicationException("BEEXALUMNI_ID 不能为空", 400);
        }

        BO info =SDK.getBOAPI().query("BO_EU_XIAOYOUJIAOHUAN").addQuery("EXCHANGE_ALUMNI_ID = ", EXALUMNI_ID)
                .addQuery("BEEXCHANGE_ALUMNI_ID = ", BEEXALUMNI_ID).detail();

        if (status.equals("交换")) {
            info.set("EXCHANGE_STATUS", "已交换");
        } else if (status.equals("拒绝")) {
            info.set("EXCHANGE_STATUS", "已拒绝");
        }

        SDK.getBOAPI().update("BO_EU_XIAOYOUJIAOHUAN",info);

        return new ObjectMapper().writeValueAsString(Map.of("status", "success"));
    }

    @POST
    @Path("/api/upload/avatar")
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    @Produces(MediaType.APPLICATION_JSON)
    public Response uploadAvatarOnly(
            @QueryParam("ALUMNI_ID") String alumniId,          // 来自 URL 查询参数
            @FormParam("ALUMNI_COVER") InputStream avatarStream,
            @FormParam("ALUMNI_COVER") String fileName) throws Exception {

        // 添加調試日誌
        System.out.println("=== 文件上傳調試信息 ===");
        System.out.println("ALUMNI_ID: " + alumniId);
        System.out.println("Stream: " + (avatarStream != null ? "存在" : "為空"));
        System.out.println("FileName: " + fileName);
        System.out.println("========================");

        try {
            // 1. 参数校验
            if (alumniId == null || alumniId.trim().isEmpty()) {
                throw new WebApplicationException("ALUMNI_ID 不能为空", 400);
            }
            if (avatarStream == null) {
                throw new WebApplicationException("头像文件 ALUMNI_COVER 不能为空", 400);
            }

            // 2. 查询校友记录
            BO alumni = SDK.getBOAPI()
                    .query("BO_EU_XIAOYOUXINXI")
                    .addQuery("ALUMNI_ID = ", alumniId)
                    .detail();
            if (alumni == null) {
                throw new WebApplicationException("未找到校友记录", 404);
            }

            // 3. 設置默認文件名
            if (fileName == null || fileName.trim().isEmpty()) {
                fileName = "avatar-" + System.currentTimeMillis() + ".jpg";
            }

            // 4. 真正上传头像（内部逻辑）
            uploadAvatar(alumni.getId(), avatarStream, fileName);

            // 5. 构造返回
            Map<String, Object> result = new HashMap<>();
            result.put("success", true);
            result.put("msg", "头像上传成功");
            return Response.ok(new ObjectMapper().writeValueAsString(result)).build();
            
        } catch (WebApplicationException e) {
            // 重新抛出 WebApplicationException
            throw e;
        } catch (Exception e) {
            // 记录其他异常并返回500错误
            System.err.println("头像上传异常: " + e.getMessage());
            e.printStackTrace();
            Map<String, Object> errorResult = new HashMap<>();
            errorResult.put("success", false);
            errorResult.put("msg", "头像上传失败: " + e.getMessage());
            return Response.status(500).entity(new ObjectMapper().writeValueAsString(errorResult)).build();
        }
    }

    // 備用文件上傳方法 - 使用不同的參數處理方式
    @POST
    @Path("/api/upload/avatar2")
    @Consumes("*/*")
    @Produces(MediaType.APPLICATION_JSON)
    public Response uploadAvatarAlternative(
            @QueryParam("ALUMNI_ID") String alumniId,
            @FormParam("ALUMNI_COVER") InputStream avatarStream,
            @FormParam("ALUMNI_COVER") String fileName) throws Exception {

        System.out.println("=== 備用方法調試信息 ===");
        System.out.println("ALUMNI_ID: " + alumniId);
        System.out.println("Stream: " + (avatarStream != null ? "存在" : "為空"));
        System.out.println("FileName: " + fileName);
        System.out.println("========================");

        try {
            // 1. 参数校验
            if (alumniId == null || alumniId.trim().isEmpty()) {
                throw new WebApplicationException("ALUMNI_ID 不能为空", 400);
            }
            if (avatarStream == null) {
                throw new WebApplicationException("头像文件 ALUMNI_COVER 不能为空", 400);
            }

            // 2. 查询校友记录
            BO alumni = SDK.getBOAPI()
                    .query("BO_EU_XIAOYOUXINXI")
                    .addQuery("ALUMNI_ID = ", alumniId)
                    .detail();
            if (alumni == null) {
                throw new WebApplicationException("未找到校友记录", 404);
            }

            // 3. 設置默認文件名
            if (fileName == null || fileName.trim().isEmpty()) {
                fileName = "avatar-" + System.currentTimeMillis() + ".jpg";
            }

            // 4. 真正上传头像
            uploadAvatar(alumni.getId(), avatarStream, fileName);

            // 5. 构造返回
            Map<String, Object> result = new HashMap<>();
            result.put("success", true);
            result.put("msg", "头像上传成功");
            return Response.ok(new ObjectMapper().writeValueAsString(result)).build();
            
        } catch (WebApplicationException e) {
            throw e;
        } catch (Exception e) {
            System.err.println("備用方法上傳異常: " + e.getMessage());
            e.printStackTrace();
            Map<String, Object> errorResult = new HashMap<>();
            errorResult.put("success", false);
            errorResult.put("msg", "头像上传失败: " + e.getMessage());
            return Response.status(500).entity(new ObjectMapper().writeValueAsString(errorResult)).build();
        }
    }

    @PUT
    @Path("/api/modify/personalinfo")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public String modifyPersonalInfo(Map<String, Object> payload) throws Exception {

        /* 1. 从 JSON 取主键 */
        String alumniId = Objects.toString(payload.get("ALUMNI_ID"), "").trim();
        if (alumniId.isEmpty()) {
            throw new WebApplicationException("ALUMNI_ID 不能为空", 400);
        }

        /* 2. 查库 */
        BO alumni = SDK.getBOAPI()
                .query("BO_EU_XIAOYOUXINXI")
                .addQuery("ALUMNI_ID = ", alumniId)
                .detail();
        if (alumni == null) {
            throw new WebApplicationException("未找到校友记录", 404);
        }

        /* 3. 白名单字段过滤 */
        Set<String> whiteList = Optional.ofNullable(payload.get("fieldsCsv"))
                .map(v -> new HashSet<>(Arrays.asList(v.toString().split(","))))
                .orElse(null);

        /* 强制让 CONTACT_PHONE 等于 PHONE 的值 */
//        if (payload.containsKey("PHONE")) {payload.put("CONTACT_PHONE", payload.get("PHONE"));}

        /* 4. 更新除保留字段外的所有文本字段 */
        for (Map.Entry<String, Object> e : payload.entrySet()) {
            String key = e.getKey();
            if (Set.of("ALUMNI_ID", "fieldsCsv").contains(key)) continue;
            if (whiteList == null || whiteList.contains(key)) {
                alumni.set(key, e.getValue());
            }
        }

        /* 5. 保存并返回最新数据 */
        SDK.getBOAPI().update("BO_EU_XIAOYOUXINXI", alumni);
        return new ObjectMapper().writerWithDefaultPrettyPrinter()
                .writeValueAsString(alumni.asMap());
    }

    @GET
    @Path("/api/search/org")
    public String searchOrgs(@QueryParam("keyword") String keyword,
                             @QueryParam("pageNo") Integer pageNo,
                             @QueryParam("filter") String filter) throws IOException {

        if (pageNo == null || pageNo < 1) pageNo = 1;
        int pageSize = 10;
        int offset = (pageNo - 1) * pageSize;

        // 调用工具类解码 keyword
        keyword = decodeKeyword(keyword);

        /* 1. 只保留 keyword 模糊条件 */
        String sql = "SELECT * " +
                        "FROM BO_EU_XIAOYOUHUIZUZHIXINXI " +
                        "WHERE 1=1 ";


        if (filter != null && !filter.trim().isEmpty()) {
            if (keyword != null && !keyword.trim().isEmpty()) {
                switch (filter){
                    case "模糊":
                        sql += "AND (ORG_NAME LIKE '%" + keyword.trim() + "%') ";
                        break;
                    case "分类":
                        sql += "AND (ORG_TYPE LIKE '%" + keyword.trim() + "%') ";
                        break;
                }
            }
        }

        sql += "ORDER BY CREATEDATE DESC, ORG_NAME DESC "
                + "LIMIT " + pageSize + " OFFSET " + offset;

        /* 2. 查询 & 组装（与原风格一致） */
        List<BO> extendinfo = SDK.getBOAPI()
                .query("BO_EU_XIAOYOUHUIZUZHIXINXI")
                .sql(sql)
                .list();

        List<Map<String, Object>> result = new ArrayList<>();
        for (BO org : extendinfo) {
            String orgId = org.getId();

            long actCnt = SDK.getBOAPI()
                    .query("BO_EU_1752895052880")
                    .addQuery("ORG_ID =", org.get("ORG_ID"))
                    .addQuery("STATUS !=", "未发布")
                    .count();

            long memCnt = SDK.getBOAPI()
                    .query("BO_EU_XIAOYOUHUIZUZHICHENGYUAN")
                    .addQuery("ORG_ID =", org.get("ORG_ID"))
                    .addQuery("AUDIT_STATUS !=", "待审核")
                    .count();

            Map<String, Object> map = new LinkedHashMap<>();
            map.put("org_id", org.get("ORG_ID"));
            map.put("org_name", org.get("ORG_NAME"));
            map.put("org_picture", buildFileUrl(org.getId(),"ORG_PICTURE"));
            map.put("activity_count", actCnt);
            map.put("member_count", memCnt);
            result.add(map);
        }

        return new ObjectMapper().writerWithDefaultPrettyPrinter()
                .writeValueAsString(result);
    }


    @GET
    @Path("/api/alumni/search")
    public String searchAlumni(
            @QueryParam("filter")  String filter,     // 全部｜同级｜同城｜同行｜同院｜模糊
            @QueryParam("keyword") String keyword,
            @QueryParam("page")  Integer page) throws IOException {

        /* ---------- 0. 基础校验 ---------- */
        if (filter == null || filter.trim().isEmpty()) {
            return new ObjectMapper().writeValueAsString(Collections.emptyList());
        }
        if (page == null || page < 1) page = 1;
        int pageSize = 10;
        int offset   = (page - 1) * pageSize;
        List<BO> infos = new ArrayList<>();
        List<String> ids = new ArrayList<>();
        List<Map<String, Object>> result = new ArrayList<>();
        // 调用工具类解码 keyword
        keyword = decodeKeyword(keyword);
        switch (filter.trim()) {
            case "全部":
                String allSql = "SELECT * FROM BO_EU_XIAOYOUXINXI WHERE AUTH_STATUS = ?";
                Object[] allParams = new Object[]{"已注册"};
                List<BO> newinfos = DBSql.getList(allSql, BO.class, allParams);
                for (BO info : newinfos) {
                    Map<String, Object> map = new LinkedHashMap<>();
                    String url = buildFileUrl(info.getId(),"ALUMNI_COVER");
                    map.put("ALUMNI_ID",info.get("ALUMNI_ID"));
                    map.put("ALUMNI_NAME",info.get("ALUMNI_NAME"));
                    map.put("ALUMNI_COVER", url);
                    result.add(map);
                }
                // 统一分页处理
                break;
            case "同级":
                    infos = SDK.getBOAPI().query("BO_EU_XIAOYOUXINXI").addQuery("AUTH_STATUS =","已注册")
                            .addQuery("COLLEGE_IN =",keyword).list();
                System.out.println("搜索到了多少校友:"+infos.size());
                break;
            case "同城":
                String sql = "SELECT A.ALUMNI_ID FROM BO_EU_XIAOYOUXINXI A " +
                               "JOIN BO_EU_XIAOYOUTUOZHANXINXI B ON A.ALUMNI_ID = B.ALUMNI_ID " +
                                "WHERE A.AUTH_STATUS = ? AND B.AREA_MAPPING LIKE ?";
                        Object[] object  = new Object[]{"已注册","%" + keyword + "%"};
                        ids = DBSql.getList(sql,String.class,object);
                break;
            case "同行":
                    infos = SDK.getBOAPI().query("BO_EU_XIAOYOUTUOZHANXINXI")
                            .addQuery("WORK_INDUSTRY =",keyword).list();

                break;
            case "同院":
                    infos = SDK.getBOAPI().query("BO_EU_XIAOYOUXINXI").addQuery("AUTH_STATUS =","已注册")
                            .addQuery("COLLEGE_NAME =",keyword).list();

                break;
            case "模糊":
                String fuzzySql = "SELECT ALUMNI_ID FROM BO_EU_XIAOYOUXINXI WHERE AUTH_STATUS = ? AND ALUMNI_NAME LIKE ?";
                Object[] params = new Object[]{"已注册", "%" + keyword + "%"};
                ids = DBSql.getList(fuzzySql, String.class, params);
                break;
            default:
                return new ObjectMapper().writeValueAsString(Collections.emptyList());
        }

        /* ---------- 3. 组装结果 ---------- */
        if (!infos.isEmpty()) {
            System.out.println("如果infos不为空组装校友学号:");
            for (BO bo : infos) {
                String ALUMNI_ID = bo.get("ALUMNI_ID").toString();
                ids.add(ALUMNI_ID);
            }
        }
        for (String id : ids) {
            System.out.println(id);
            Map<String, Object> map = SDK.getBOAPI()
                    .query("BO_EU_XIAOYOUTUOZHANXINXI").addQuery("ALUMNI_ID =", id)
                    .detail().asMap();
            System.out.println("mappID="+map.get("ALUMNI_ID"));
            BO info = SDK.getBOAPI().query("BO_EU_XIAOYOUXINXI").addQuery("ALUMNI_ID =", id).detail();
            String url = buildFileUrl(info.getId(), "ALUMNI_COVER");
            map.put("ALUMNI_ID", info.get("ALUMNI_ID"));
            map.put("ALUMNI_NAME", info.get("ALUMNI_NAME"));
            System.out.println("mappName="+map.get("ALUMNI_NAME"));
            map.put("ALUMNI_COVER", url);
            result.add(map);
        }
        
        /* ---------- 4. 统一分页处理 ---------- */
        // 对最终组装好的结果列表进行分页
        int totalSize = result.size();
        int startIndex = Math.min(offset, totalSize);
        int endIndex = Math.min(offset + pageSize, totalSize);
        
        List<Map<String, Object>> pagedResult = result.subList(startIndex, endIndex);
        
        return new ObjectMapper().writerWithDefaultPrettyPrinter()
                .writeValueAsString(pagedResult);
    }

    @POST
    @Path("/api/addexchange")
    public String addexchange(@QueryParam("EXCHANGE_ALUMNI_ID") String EXCHANGE_ALUMNI_ID,
                              @QueryParam("BEEXCHANGE_ALUMNI_ID") String BEEXCHANGE_ALUMNI_ID) throws IOException {
        System.out.println("EX:"+EXCHANGE_ALUMNI_ID);
        System.out.println("BEEX:"+BEEXCHANGE_ALUMNI_ID);
//创建流程id，启动流程获取流程id
        ProcessInstance process = SDK.getProcessAPI().createProcessInstance
                ("obj_8747db30cd324e1e925e1111697bdda6","admin","添加交换信息流程");
        SDK.getProcessAPI().start(process);
        String bindid=process.getId();
//创建新BO，保存信息
        BO bo = new BO();
        bo.set("EXCHANGE_ALUMNI_ID",EXCHANGE_ALUMNI_ID);
        bo.set("BEEXCHANGE_ALUMNI_ID",BEEXCHANGE_ALUMNI_ID);
        bo.set("EXCHANGE_ALUMNI_NAME",SDK.getBOAPI().query("BO_EU_XIAOYOUXINXI").addQuery("ALUMNI_ID =",EXCHANGE_ALUMNI_ID).list().get(0).get("ALUMNI_NAME"));
        bo.set("BEEXCHANGE_ALUMNI_NAME",SDK.getBOAPI().query("BO_EU_XIAOYOUXINXI").addQuery("ALUMNI_ID =",BEEXCHANGE_ALUMNI_ID).list().get(0).get("ALUMNI_NAME"));
        bo.set("BINDID",bindid);
        int count = SDK.getBOAPI().create("BO_EU_XIAOYOUJIAOHUAN",bo,bindid,EXCHANGE_ALUMNI_ID);//写死账户需修改

        if (count == 0) {
            return "交换失败，出现异常";
        }

        String issuccess = autocompleteTask(process.getStartTaskInstId(),EXCHANGE_ALUMNI_ID);
        //返回成功 JSON
        Map<String, Object> result = new HashMap<>();
        result.put("count", count);
        result.put("msg", issuccess);

        return new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(result);
    }

    /*-----------------------------2-------------------------------*/
    //2.5.3
    @GET
    @Path("/api/getdetail/activity")
    public String getdeac(@QueryParam("ACTIVITY_ID") String ACTIVITY_ID) throws IOException{
        Map<String,Object> activity = SDK.getBOAPI().query("BO_EU_1752895052880")
                .addQuery("ACTIVITY_ID =",ACTIVITY_ID)
                .detail().asMap();
        BO org = SDK.getBOAPI().query("BO_EU_XIAOYOUHUIZUZHIXINXI")
                .addQuery("ORG_ID =",activity.get("ORG_ID")).list().get(0);
        Long total = SDK.getBOAPI().query("BO_EU_REGISTRATION_INFORMATION")
                .addQuery("ACTIVITY_ID =",ACTIVITY_ID).count();
        activity.put("ACTIVITY_COVER",buildFileUrl((String) activity.get("ID"),"ACTIVITY_COVER"));
        activity.put("TOTAL",total);
        activity.put("ORG_PICTURE",buildFileUrl(org.getId(),"ORG_PICTURE"));
        activity.put("ORG_NAME",org.get("ORG_NAME"));
        return new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(activity);
    }

    /*-----------------------------2-------------------------------*/

    /*-----------------------------4-------------------------------*/
    @POST
    @Path("/api/joinorg")
    public String org(@QueryParam("ALUMNI_ID") String ALUMNI_ID,
                          @QueryParam("ORG_ID") String ORG_ID,
                          @DefaultValue("成员") @QueryParam("ROLE_TYPE") String ROLE_TYPE) throws IOException {
        if (ALUMNI_ID == null || ORG_ID == null) {
            return "请携带学工号和组织id";
        }
        //创建流程id，启动流程获取流程id
        ProcessInstance process = SDK.getProcessAPI().createProcessInstance
                ("obj_6cce7fb4d31540d39ff757b3ca807265",ALUMNI_ID,"申请加入组织流程");
        SDK.getProcessAPI().start(process);
        String bindid=process.getId();
//创建新BO，保存信息
        BO bo = new BO();
        bo.set("ALUMNI_ID",ALUMNI_ID);
        bo.set("ALUMNI_NAME",SDK.getBOAPI().query("BO_EU_XIAOYOUXINXI").addQuery("ALUMNI_ID =",ALUMNI_ID).detail().get("ALUMNI_NAME"));
        bo.set("ORG_ID",ORG_ID);
        bo.set("ORG_NAME",SDK.getBOAPI().query("BO_EU_XIAOYOUHUIZUZHIXINXI").addQuery("ORG_ID =",ORG_ID).detail().get("ORG_NAME"));
        bo.set("ROLE_TYPE",ROLE_TYPE);
        bo.set("AUDIT_STATUS","待审核");
        bo.set("BINDID",bindid);
        int count = SDK.getBOAPI().create("BO_EU_XIAOYOUHUIZUZHICHENGYUAN",bo,bindid,ALUMNI_ID);
        if (count == 0) {
            return "申请失败,出现异常";
        }
        //自动完成填写的步骤
        String issuccess = autocompleteTask(process.getStartTaskInstId(),ALUMNI_ID);
        //返回成功 JSON
        Map<String, Object> result = new HashMap<>();
        result.put("count", count);
        result.put("AUDIT_STATUS",SDK.getBOAPI().getByProcess("BO_EU_XIAOYOUHUIZUZHICHENGYUAN",bindid,"AUDIT_STATUS"));
        result.put("AUDIT_NAME",SDK.getBOAPI().getByProcess("BO_EU_XIAOYOUHUIZUZHICHENGYUAN",bindid,"ALUMNI_NAME"));
        result.put("msg", issuccess);

        return new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(result);
    }


    /*-----------------------------4-------------------------------*/



    @POST
    @Path("/getPhoneNumber")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public String getPhoneNumber(String body) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        JsonNode node = mapper.readTree(body);
        String code = node.get("code").asText();

        // 1. 获取 access_token
        String tokenUrl = "https://api.weixin.qq.com/cgi-bin/token"
                + "?grant_type=client_credential"
                + "&appid=" + APP_ID
                + "&secret=" + APP_SECRET;

        String tokenResp = ClientBuilder.newClient()
                .target(tokenUrl)
                .request()
                .get(String.class);

        String accessToken = mapper.readTree(tokenResp)
                .get("access_token")
                .asText();

        // 2. 用 code 获取手机号
        String phoneUrl = "https://api.weixin.qq.com/wxa/business/getuserphonenumber"
                + "?access_token=" + accessToken;

        // ✅ 手动构造 JSON 字符串，避免序列化问题
        String jsonBody = "{\"code\":\"" + code + "\"}";

        String phoneResp = ClientBuilder.newClient()
                .target(phoneUrl)
                .request()
                .post(Entity.json(jsonBody), String.class);

        JsonNode phoneNode = mapper.readTree(phoneResp);
        if (!"0".equals(phoneNode.get("errcode").asText())) {
            throw new WebApplicationException(phoneNode.get("errmsg").asText(), 400);
        }

        String mobile = phoneNode.get("phone_info")
                .get("purePhoneNumber")
                .asText();

        return mapper.writeValueAsString(Map.of("phoneNumber", mobile));
    }

    /*-----------------------------额外的类-------------------------------*/
    @POST
    @Path("/api/synsManager")
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    @Produces(MediaType.APPLICATION_JSON)
    public String synsManager(@FormParam("oldmanager") String olduniqueId,
                              @FormParam("newmanager") String newuniqueId,
                              @FormParam("departmentid") String departmentid) throws IOException {
        System.out.println("111"+olduniqueId+"222"+newuniqueId+"333"+departmentid);
        //从表单获取的新的管理员
        UserModel olduser = SDK.getORGAPI().getUserByUniqueId(olduniqueId);
        String olduid = olduser.getUID();
        System.out.println("获取到的旧管理员uid"+olduid);
        UserModel newuser = SDK.getORGAPI().getUserByUniqueId(newuniqueId);
        String newuid = newuser.getUID();
        System.out.println("获取到的新管理员uid"+newuid);
        //修改组织管理员
        SDK.getORGAPI().cancelDepartmentManager(departmentid, olduid);
        System.out.println("当前的管理员："+SDK.getORGAPI().getManagersByDepartment(departmentid).get(0).getUserName());
        SDK.getORGAPI().assertDepartmentManager(departmentid, newuid);
        System.out.println("当前的管理员："+SDK.getORGAPI().getManagersByDepartment(departmentid).get(0).getUserName());

        return "success";
    }


    /*-----------------------------额外的类-------------------------------*/


    /*-----------------------------工具类-------------------------------*/


/* 头像上传实例方法（非 static，避免内部类 static 限制）*/
private void uploadAvatar(String alumniId, InputStream data, String fileName) {
    try (InputStream in = data) {
        FormFileModel form = new FormFileModel();
        form.setBoId(alumniId);
        form.setBoName("BO_EU_XIAOYOUXINXI");
        form.setBoItemName("ALUMNI_COVER");
        form.setCreateUser("admin");
        form.setAppId("com.awspaas.user.apps.xiaoyouhui");
        if (fileName == null || fileName.trim().isEmpty()) {
            fileName = "avatar-" + System.currentTimeMillis() + ".png";
        }
        form.setFileName(fileName);
        SDK.getBOAPI().upFile(form, "repository", in);
    } catch (Exception e) {
        throw new AWSDataAccessException("头像上传失败：" + e.getMessage(), e);
    }
}



    //获得图片
    private List<String> getFieldFileUrls(String boid, String field) throws IOException {
        List<FormFile> files = SDK.getBOAPI().getFiles(boid, field);
        if (files == null || files.isEmpty()) {
            return Collections.emptyList();
        }

        // 这里只取第一条文件，如有多文件可自行循环
        return Collections.singletonList(buildFileUrl(boid, field));
    }

    /*String uid, String pwd*/
    private String createClientSession() throws IOException {
        // 假设 SDK 返回的是整段 JSON 字符串
        String json = SDK.getPortalAPI().createClientSession("admin", "123"); // 固定账号返回sid
        ObjectMapper mapper = new ObjectMapper();
        // 只抓 sid
        return mapper.readTree(json).path("data").path("sid").asText();
    }

    private String buildFileUrl(String boid, String field) throws IOException {

        String sid = createClientSession();
        List<FormFile> files = SDK.getBOAPI().getFiles(boid, field);
        if (files == null || files.isEmpty()) {
            return null;
        }
        DCContext context = SDK.getBOAPI().getFileDCContext(files.get(0));
        String url = context.getDownloadURL();      // 形如 "./df?sid=xxxxx..."
        url = url.replaceFirst("\\./df\\?sid=[^&]*", "/r/df?sid=" + sid); // 替换 sid
        String baseUrl = "https://xysq.bitzh.edu.cn";
        return baseUrl + url;
    }

        /**
         * 解码 URL 编码的字符串
         * @param encodedStr URL 编码的字符串
         * @return 解码后的字符串，如果解码失败则返回空字符串
         */
    public static String decodeKeyword(String encodedStr) {
        if (encodedStr == null || encodedStr.trim().isEmpty()) {
            return "";
        }
        try {
            return URLDecoder.decode(encodedStr, "UTF-8");
        } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
                return ""; // 如果解码失败，返回空字符串
        }
    }
    //自动完成填写任务接口
    public static String autocompleteTask(String Taskid,String uid) {
        String issuccess = SDK.getTaskAPI().completeTask(Taskid,uid).toString();

        return issuccess;
    }


}
